using NUnit.Framework;

namespace Drill.Core.Utilities.Extensions
{
    [TestFixture]
    public class StringExtensionMethodsTests
    {
        [Test]
        public void CanDirectlyExecuteToBooleanWithoutDefaultValue()
        {
            // ReSharper disable InvokeAsExtensionMethod

            // These test explicitly resolve to false.
            Assert.That(StringExtensionMethods.ToBoolean("0"), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("f"), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("F"), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("false"), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("False"), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("FALSE"), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("n"), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("N"), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("no"), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("No"), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("NO"), Is.False);

            // These test explicitly resolve to true.
            Assert.That(StringExtensionMethods.ToBoolean("1"), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("t"), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("T"), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("true"), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("True"), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("TRUE"), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("y"), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("Y"), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("yes"), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("Yes"), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("YES"), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("Y"), Is.True);

            // These tests will be false because they resolve to the default value, false.
            Assert.That(StringExtensionMethods.ToBoolean(null), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean(""), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("a"), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("asdf"), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("123"), Is.False);
            
            // ReSharper restore InvokeAsExtensionMethod
        }

        [Test]
        public void CanDirectlyExecuteToBooleanWithDefaultValue()
        {
            // ReSharper disable InvokeAsExtensionMethod

            // These test explicitly resolve to false.
            Assert.That(StringExtensionMethods.ToBoolean("0", true), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("f", true), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("F", true), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("false", true), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("False", true), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("FALSE", true), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("n", true), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("N", true), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("no", true), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("No", true), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("NO", true), Is.False);

            // These test explicitly resolve to true.
            Assert.That(StringExtensionMethods.ToBoolean("1", false), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("t", false), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("T", false), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("true", false), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("True", false), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("TRUE", false), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("y", false), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("Y", false), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("yes", false), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("Yes", false), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("YES", false), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("Y", false), Is.True);

            // These tests will be false because they resolve to the specified default value, false.
            Assert.That(StringExtensionMethods.ToBoolean(null, false), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("", false), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("a", false), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("asdf", false), Is.False);
            Assert.That(StringExtensionMethods.ToBoolean("123", false), Is.False);

            // These tests will be true because they resolve to the specified default value, true.
            Assert.That(StringExtensionMethods.ToBoolean(null, true), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("", true), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("a", true), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("asdf", true), Is.True);
            Assert.That(StringExtensionMethods.ToBoolean("123", true), Is.True);

            // ReSharper restore InvokeAsExtensionMethod
        }

        [Test]
        public void CanExecuteAsExtensionMethodToBooleanWithoutDefaultValue()
        {
            // These test explicitly resolve to false.
            Assert.That("0".ToBoolean(), Is.False);
            Assert.That("f".ToBoolean(), Is.False);
            Assert.That("F".ToBoolean(), Is.False);
            Assert.That("false".ToBoolean(), Is.False);
            Assert.That("False".ToBoolean(), Is.False);
            Assert.That("FALSE".ToBoolean(), Is.False);
            Assert.That("n".ToBoolean(), Is.False);
            Assert.That("N".ToBoolean(), Is.False);
            Assert.That("no".ToBoolean(), Is.False);
            Assert.That("No".ToBoolean(), Is.False);
            Assert.That("NO".ToBoolean(), Is.False);

            // These test explicitly resolve to true.
            Assert.That("1".ToBoolean(), Is.True);
            Assert.That("t".ToBoolean(), Is.True);
            Assert.That("T".ToBoolean(), Is.True);
            Assert.That("true".ToBoolean(), Is.True);
            Assert.That("True".ToBoolean(), Is.True);
            Assert.That("TRUE".ToBoolean(), Is.True);
            Assert.That("y".ToBoolean(), Is.True);
            Assert.That("Y".ToBoolean(), Is.True);
            Assert.That("yes".ToBoolean(), Is.True);
            Assert.That("Yes".ToBoolean(), Is.True);
            Assert.That("YES".ToBoolean(), Is.True);
            Assert.That("Y".ToBoolean(), Is.True);

            // These tests will be false because they resolve to the default value, false.
            Assert.That("".ToBoolean(), Is.False);
            Assert.That("a".ToBoolean(), Is.False);
            Assert.That("asdf".ToBoolean(), Is.False);
            Assert.That("123".ToBoolean(), Is.False);
        }

        [Test]
        public void CanExecuteAsExtensionMethodToBooleanWithDefaultValue()
        {
            // These test explicitly resolve to false.
            Assert.That("0".ToBoolean(true), Is.False);
            Assert.That("f".ToBoolean(true), Is.False);
            Assert.That("F".ToBoolean(true), Is.False);
            Assert.That("false".ToBoolean(true), Is.False);
            Assert.That("False".ToBoolean(true), Is.False);
            Assert.That("FALSE".ToBoolean(true), Is.False);
            Assert.That("n".ToBoolean(true), Is.False);
            Assert.That("N".ToBoolean(true), Is.False);
            Assert.That("no".ToBoolean(true), Is.False);
            Assert.That("No".ToBoolean(true), Is.False);
            Assert.That("NO".ToBoolean(true), Is.False);

            // These test explicitly resolve to true.
            Assert.That("1".ToBoolean(false), Is.True);
            Assert.That("t".ToBoolean(false), Is.True);
            Assert.That("T".ToBoolean(false), Is.True);
            Assert.That("true".ToBoolean(false), Is.True);
            Assert.That("True".ToBoolean(false), Is.True);
            Assert.That("TRUE".ToBoolean(false), Is.True);
            Assert.That("y".ToBoolean(false), Is.True);
            Assert.That("Y".ToBoolean(false), Is.True);
            Assert.That("yes".ToBoolean(false), Is.True);
            Assert.That("Yes".ToBoolean(false), Is.True);
            Assert.That("YES".ToBoolean(false), Is.True);
            Assert.That("Y".ToBoolean(false), Is.True);

            // These tests will be false because they resolve to the specified default value, false.
            Assert.That("".ToBoolean(false), Is.False);
            Assert.That("a".ToBoolean(false), Is.False);
            Assert.That("asdf".ToBoolean(false), Is.False);
            Assert.That("123".ToBoolean(false), Is.False);

            // These tests will be true because they resolve to the specified default value, true.
            Assert.That("".ToBoolean(true), Is.True);
            Assert.That("a".ToBoolean(true), Is.True);
            Assert.That("asdf".ToBoolean(true), Is.True);
            Assert.That("123".ToBoolean(true), Is.True);
        }

        [Test]
        public void CanDirectlyExecuteToInt32WithoutDefaultValue()
        {
            // ReSharper disable InvokeAsExtensionMethod

            // These test explicitly resolve to an Int32 value.
            Assert.That(StringExtensionMethods.ToInt32("0"), Is.EqualTo(0));
            Assert.That(StringExtensionMethods.ToInt32("1"), Is.EqualTo(1));
            Assert.That(StringExtensionMethods.ToInt32("2"), Is.EqualTo(2));
            Assert.That(StringExtensionMethods.ToInt32("3"), Is.EqualTo(3));
            Assert.That(StringExtensionMethods.ToInt32("101"), Is.EqualTo(101));
            Assert.That(StringExtensionMethods.ToInt32("1234"), Is.EqualTo(1234));
            Assert.That(StringExtensionMethods.ToInt32("32767"), Is.EqualTo(32767));
            Assert.That(StringExtensionMethods.ToInt32("100298"), Is.EqualTo(100298));
            Assert.That(StringExtensionMethods.ToInt32("1234567"), Is.EqualTo(1234567));
            Assert.That(StringExtensionMethods.ToInt32("12345678"), Is.EqualTo(12345678));
            Assert.That(StringExtensionMethods.ToInt32("-1"), Is.EqualTo(-1));
            Assert.That(StringExtensionMethods.ToInt32("-2"), Is.EqualTo(-2));
            Assert.That(StringExtensionMethods.ToInt32("-3"), Is.EqualTo(-3));
            Assert.That(StringExtensionMethods.ToInt32("-101"), Is.EqualTo(-101));
            Assert.That(StringExtensionMethods.ToInt32("-1234"), Is.EqualTo(-1234));
            Assert.That(StringExtensionMethods.ToInt32("-32767"), Is.EqualTo(-32767));
            Assert.That(StringExtensionMethods.ToInt32("-100298"), Is.EqualTo(-100298));
            Assert.That(StringExtensionMethods.ToInt32("-1234567"), Is.EqualTo(-1234567));
            Assert.That(StringExtensionMethods.ToInt32("-12345678"), Is.EqualTo(-12345678));

            // These tests will resolve to -1 because they resolve to the default value, -1.
            Assert.That(StringExtensionMethods.ToInt32(null), Is.EqualTo(-1));
            Assert.That(StringExtensionMethods.ToInt32(""), Is.EqualTo(-1));
            Assert.That(StringExtensionMethods.ToInt32("a"), Is.EqualTo(-1));
            Assert.That(StringExtensionMethods.ToInt32("asdf"), Is.EqualTo(-1));
            Assert.That(StringExtensionMethods.ToInt32("l23"), Is.EqualTo(-1));

            // ReSharper restore InvokeAsExtensionMethod
        }

        [Test]
        public void CanDirectlyExecuteToInt32WithDefaultValue()
        {
            // ReSharper disable InvokeAsExtensionMethod

            // These test explicitly resolve to an Int32 value.
            Assert.That(StringExtensionMethods.ToInt32("0", 42), Is.EqualTo(0));
            Assert.That(StringExtensionMethods.ToInt32("1", 42), Is.EqualTo(1));
            Assert.That(StringExtensionMethods.ToInt32("2", 42), Is.EqualTo(2));
            Assert.That(StringExtensionMethods.ToInt32("3", 42), Is.EqualTo(3));
            Assert.That(StringExtensionMethods.ToInt32("101", 42), Is.EqualTo(101));
            Assert.That(StringExtensionMethods.ToInt32("1234", 42), Is.EqualTo(1234));
            Assert.That(StringExtensionMethods.ToInt32("32767", 42), Is.EqualTo(32767));
            Assert.That(StringExtensionMethods.ToInt32("100298", 42), Is.EqualTo(100298));
            Assert.That(StringExtensionMethods.ToInt32("1234567", 42), Is.EqualTo(1234567));
            Assert.That(StringExtensionMethods.ToInt32("12345678", 42), Is.EqualTo(12345678));
            Assert.That(StringExtensionMethods.ToInt32("-1", 42), Is.EqualTo(-1));
            Assert.That(StringExtensionMethods.ToInt32("-2", 42), Is.EqualTo(-2));
            Assert.That(StringExtensionMethods.ToInt32("-3", 42), Is.EqualTo(-3));
            Assert.That(StringExtensionMethods.ToInt32("-101", 42), Is.EqualTo(-101));
            Assert.That(StringExtensionMethods.ToInt32("-1234", 42), Is.EqualTo(-1234));
            Assert.That(StringExtensionMethods.ToInt32("-32767", 42), Is.EqualTo(-32767));
            Assert.That(StringExtensionMethods.ToInt32("-100298", 42), Is.EqualTo(-100298));
            Assert.That(StringExtensionMethods.ToInt32("-1234567", 42), Is.EqualTo(-1234567));
            Assert.That(StringExtensionMethods.ToInt32("-12345678", 42), Is.EqualTo(-12345678));

            // These tests will resolve to 42 because they resolve to the specified default value, 42.
            Assert.That(StringExtensionMethods.ToInt32(null, 42), Is.EqualTo(42));
            Assert.That(StringExtensionMethods.ToInt32("", 42), Is.EqualTo(42));
            Assert.That(StringExtensionMethods.ToInt32("a", 42), Is.EqualTo(42));
            Assert.That(StringExtensionMethods.ToInt32("asdf", 42), Is.EqualTo(42));
            Assert.That(StringExtensionMethods.ToInt32("l23", 42), Is.EqualTo(42));

            // ReSharper restore InvokeAsExtensionMethod
        }

        [Test]
        public void CanExecuteAsExtensionMethodToInt32WithoutDefaultValue()
        {
            // These test explicitly resolve to an Int32 value.
            Assert.That("0".ToInt32(), Is.EqualTo(0));
            Assert.That("1".ToInt32(), Is.EqualTo(1));
            Assert.That("2".ToInt32(), Is.EqualTo(2));
            Assert.That("3".ToInt32(), Is.EqualTo(3));
            Assert.That("101".ToInt32(), Is.EqualTo(101));
            Assert.That("1234".ToInt32(), Is.EqualTo(1234));
            Assert.That("32767".ToInt32(), Is.EqualTo(32767));
            Assert.That("100298".ToInt32(), Is.EqualTo(100298));
            Assert.That("1234567".ToInt32(), Is.EqualTo(1234567));
            Assert.That("12345678".ToInt32(), Is.EqualTo(12345678));
            Assert.That("-1".ToInt32(), Is.EqualTo(-1));
            Assert.That("-2".ToInt32(), Is.EqualTo(-2));
            Assert.That("-3".ToInt32(), Is.EqualTo(-3));
            Assert.That("-101".ToInt32(), Is.EqualTo(-101));
            Assert.That("-1234".ToInt32(), Is.EqualTo(-1234));
            Assert.That("-32767".ToInt32(), Is.EqualTo(-32767));
            Assert.That("-100298".ToInt32(), Is.EqualTo(-100298));
            Assert.That("-1234567".ToInt32(), Is.EqualTo(-1234567));
            Assert.That("-12345678".ToInt32(), Is.EqualTo(-12345678));

            // These tests will resolve to -1 because they resolve to the default value, -1.
            Assert.That("".ToInt32(), Is.EqualTo(-1));
            Assert.That("a".ToInt32(), Is.EqualTo(-1));
            Assert.That("asdf".ToInt32(), Is.EqualTo(-1));
            Assert.That("l23".ToInt32(), Is.EqualTo(-1));
        }

        [Test]
        public void CanExecuteAsExtensionMethodToInt32WithDefaultValue()
        {
            // These test explicitly resolve to an Int32 value.
            Assert.That("0".ToInt32(42), Is.EqualTo(0));
            Assert.That("1".ToInt32(42), Is.EqualTo(1));
            Assert.That("2".ToInt32(42), Is.EqualTo(2));
            Assert.That("3".ToInt32(42), Is.EqualTo(3));
            Assert.That("101".ToInt32(42), Is.EqualTo(101));
            Assert.That("1234".ToInt32(42), Is.EqualTo(1234));
            Assert.That("32767".ToInt32(42), Is.EqualTo(32767));
            Assert.That("100298".ToInt32(42), Is.EqualTo(100298));
            Assert.That("1234567".ToInt32(42), Is.EqualTo(1234567));
            Assert.That("12345678".ToInt32(42), Is.EqualTo(12345678));
            Assert.That("-1".ToInt32(42), Is.EqualTo(-1));
            Assert.That("-2".ToInt32(42), Is.EqualTo(-2));
            Assert.That("-3".ToInt32(42), Is.EqualTo(-3));
            Assert.That("-101".ToInt32(42), Is.EqualTo(-101));
            Assert.That("-1234".ToInt32(42), Is.EqualTo(-1234));
            Assert.That("-32767".ToInt32(42), Is.EqualTo(-32767));
            Assert.That("-100298".ToInt32(42), Is.EqualTo(-100298));
            Assert.That("-1234567".ToInt32(42), Is.EqualTo(-1234567));
            Assert.That("-12345678".ToInt32(42), Is.EqualTo(-12345678));

            // These tests will resolve to 42 because they resolve to the specified default value, 42.
            Assert.That("".ToInt32(42), Is.EqualTo(42));
            Assert.That("a".ToInt32(42), Is.EqualTo(42));
            Assert.That("asdf".ToInt32(42), Is.EqualTo(42));
            Assert.That("l23".ToInt32(42), Is.EqualTo(42));
        }
    }
}